/* Recursive subdivision of triangle */
#include <Windows.h>
#include <GL/glut.h>
#include <math.h>

/* initial triangle */

GLfloat twistmv[3][2] = { { -1.0, -0.58 }, { 1.0, -0.58 }, { 0.0, 1.15 } };

int twistmn;
float twist;

void twistmtriangle(GLfloat *a, GLfloat *b, GLfloat *c, int type)

/* display one triangle  */
{
	GLfloat v[2];
	double d;
	glBegin(GL_POLYGON);
	switch (type) {
	case (2):
	case (4):
	case (6):
	case (7):
		glEdgeFlag(GL_FALSE);
		break;
	default:
		glEdgeFlag(GL_TRUE);
	}
	d = sqrt(a[0] * a[0] + a[1] * a[1]);
	v[0] = cos(twist * d) * a[0] - sin(twist * d) * a[1];
	v[1] = sin(twist * d) * a[0] + cos(twist * d) * a[1];
	glVertex2fv(v);
	switch (type) {
	case (3):
	case (4):
	case (5):
	case (7):
		glEdgeFlag(GL_FALSE);
		break;
	default:
		glEdgeFlag(GL_TRUE);
	}
	d = sqrt(b[0] * b[0] + b[1] * b[1]);
	v[0] = cos(twist * d) * b[0] - sin(twist * d) * b[1];
	v[1] = sin(twist * d) * b[0] + cos(twist * d) * b[1];
	glVertex2fv(v);
	switch (type) {
	case (1):
	case (5):
	case (6):
	case (7):
		glEdgeFlag(GL_FALSE);
		break;
	default:
		glEdgeFlag(GL_TRUE);
	}
	d = sqrt(c[0] * c[0] + c[1] * c[1]);
	v[0] = cos(twist * d) * c[0] - sin(twist * d) * c[1];
	v[1] = sin(twist * d) * c[0] + cos(twist * d) * c[1];
	glVertex2fv(v);
	glEnd();
}

void twistmdivide_triangle(GLfloat *a, GLfloat *b, GLfloat *c, int m, int k) {

	/* triangle subdivision using vertex numbers */

	GLfloat v[3][2];
	int j, flag[4];
	if (m > 0) {
		for (j = 0; j < 2; j++)
			v[0][j] = (a[j] + b[j]) / 2;
		for (j = 0; j < 2; j++)
			v[1][j] = (b[j] + c[j]) / 2;
		for (j = 0; j < 2; j++)
			v[2][j] = (a[j] + c[j]) / 2;
		switch (k) {
		case (0):
			flag[0] = 3;
			flag[1] = 1;
			flag[2] = 2;
			break;
		case (1):
			flag[0] = 5;
			flag[1] = 1;
			flag[2] = 6;
			break;
		case (2):
			flag[0] = 4;
			flag[1] = 6;
			flag[2] = 2;
			break;
		case (3):
			flag[0] = 3;
			flag[1] = 5;
			flag[2] = 4;
			break;
		case (4):
			flag[0] = 4;
			flag[1] = 7;
			flag[2] = 4;
			break;
		case (5):
			flag[0] = 5;
			flag[1] = 5;
			flag[2] = 7;
			break;
		case (6):
			flag[0] = 7;
			flag[1] = 6;
			flag[2] = 6;
			break;
		case (7):
			flag[0] = 7;
			flag[1] = 7;
			flag[2] = 7;
			break;
		}
		flag[3] = 7;
		twistmdivide_triangle(a, v[0], v[2], m - 1, flag[0]);
		twistmdivide_triangle(v[0], b, v[1], m - 1, flag[1]);
		twistmdivide_triangle(v[2], v[1], c, m - 1, flag[2]);
		twistmdivide_triangle(v[0], v[1], v[2], m - 1, flag[3]);
	} else
		(twistmtriangle(a, b, c, k)); /* draw triangle at end of recursion */
}

void twistmdisplay(void) {

	glClear(GL_COLOR_BUFFER_BIT);
	twistmdivide_triangle(twistmv[0], twistmv[1], twistmv[2], twistmn, 0);
	glFlush();
}

void twistmmyinit() {

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluOrtho2D(-2.0, 2.0, -2.0, 2.0);
	glMatrixMode(GL_MODELVIEW);
	glClearColor(1.0, 1.0, 1.0, 1.0);
	glColor3f(0.0, 0.0, 0.0);
	glPolygonMode(GL_FRONT, GL_LINE);
}

int twistm(int argc, char **argv) {
	twistmn = 4;
	twist = 2.0;
	glutInit(&argc, argv);
	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize(500, 500);
	glutCreateWindow("Edge Flag Test");
	glutDisplayFunc(twistmdisplay);
	twistmmyinit();
	glutMainLoop();
	return 0;
}
